package top.infopub.concurrent;


import java.util.Locale;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * code from netty
 * @author Awoke
 * @version 2018年9月13日
 * @see IncreaseNameThreadFactory
 * @since
 */
public class IncreaseNameThreadFactory implements ThreadFactory {

    private static final AtomicInteger poolId = new AtomicInteger();

    private final AtomicInteger nextId = new AtomicInteger();

    private final String prefix;

    private final boolean daemon;

    private final int priority;

    public IncreaseNameThreadFactory(Class<?> poolType) {
        this(poolType, false, Thread.NORM_PRIORITY);
    }

    public IncreaseNameThreadFactory(Class<?> poolType, boolean daemon, int priority) {
        this(toPoolName(poolType), daemon, priority);
    }

    private static String toPoolName(Class<?> poolType) {
        if (poolType == null) {
            throw new NullPointerException("poolType");
        }
        String poolName;
        Package pkg = poolType.getPackage();
        if (pkg != null) {
            poolName = poolType.getName().substring(pkg.getName().length() + 1);
        }
        else {
            poolName = poolType.getName();
        }

        switch (poolName.length()) {
            case 0:
                return "unknown";
            case 1:
                return poolName.toLowerCase(Locale.US);
            default:
                if (Character.isUpperCase(poolName.charAt(0))
                    && Character.isLowerCase(poolName.charAt(1))) {
                    return Character.toLowerCase(poolName.charAt(0)) + poolName.substring(1);
                }
                else {
                    return poolName;
                }
        }
    }

    public IncreaseNameThreadFactory(String poolName, boolean daemon, int priority) {
        if (poolName == null) {
            throw new NullPointerException("poolName");
        }
        if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
            throw new IllegalArgumentException(
                "priority: " + priority
                    + " (expected: Thread.MIN_PRIORITY <= priority <= Thread.MAX_PRIORITY)");
        }
        prefix = poolName + '-' + poolId.incrementAndGet() + '-';
        this.daemon = daemon;
        this.priority = priority;
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r, prefix + nextId.incrementAndGet());
        try {
            if (t.isDaemon()) {
                if (!daemon) {
                    t.setDaemon(false);
                }
            }
            else {
                if (daemon) {
                    t.setDaemon(true);
                }
            }
            if (t.getPriority() != priority) {
                t.setPriority(priority);
            }
        }
        catch (Exception ignored) {
            // Doesn't matter even if failed to set.
        }
        return t;
    }
}
